package com.wkck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wkck.VO.CompanyInfoVo;
import com.wkck.annotaion.ClearAllCache;
import com.wkck.config.IdGeneratorSnowflake;
import com.wkck.context.BaseContext;
import com.wkck.domain.CompanyPhoto;
import com.wkck.exception.BaseException;
import com.wkck.exception.FileNotFoundException;
import com.wkck.exception.UploadErrorException;
import com.wkck.service.CommonService;
import com.wkck.service.CompanyPhotosService;
import com.wkck.service.CompanyService;
import io.minio.MinioClient;
import io.minio.RemoveObjectArgs;
import io.minio.UploadObjectArgs;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.UUID;

/**
 * @Author: CK
 * @Date: 2024/02/10/18:51
 * @Description:
 */
@Service
@Slf4j
public class CommonServiceImpl implements CommonService {

    @Autowired
    private CompanyService companyService;

    @Autowired
    private CompanyPhotosService companyPhotosService;

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucket}")
    private String bucket;

    /***
    * @Author: CK
    * @Date: 2024/2/10
    * @Param: [localFilePath, filename, size, uuid]
    * @Description: 保存图片文件
    */
    @Override
    @Transactional
    @ClearAllCache
    public Boolean commitPhoto(String localFilePath, String filename, long size, String uuid) {
        log.info("需要保存的文件: {}, {}, {}", localFilePath, size, filename);

        File file = new File(localFilePath);
        if (!file.exists()) {
            throw new FileNotFoundException("文件未找到，上传失败!");
        }

        String fileMd5 = getFileMd5(file);

        CompanyInfoVo info = companyService.getCompanyInfoByUUID(uuid);
        if (Objects.isNull(info)) {
            throw new BaseException("添加信息为空！请重试");
        }

        if (info.getCompanyPhoto().size() >= 3) {
            throw new BaseException("该公司图片数量已达上限！");
        }

        String companyName = info.getCompany();
        Integer companyId = info.getId();
        // 防止重复
        String minioLocation = companyName + "/" + fileMd5 + "_" + UUID.randomUUID() + ".jpg";

        try {
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(bucket)
                            .object(minioLocation)
                            .filename(localFilePath)
                            .contentType("image/jpeg")
                            .build());
            log.info("图片上传成功, {}", minioLocation);
        } catch (Exception e) {
            throw new UploadErrorException("图片上传失败");
        }

        log.info("开始写入数据库");
        CompanyPhoto companyPhoto = new CompanyPhoto();
        companyPhoto.setCp_uuid(uuid);
        companyPhoto.setCompany_id(companyId);
        companyPhoto.setKey_md5(fileMd5);
        companyPhoto.setFile_name(filename);
        companyPhoto.setBucket(bucket);
        companyPhoto.setLocation(minioLocation);
        companyPhoto.setFile_size(size);

        companyPhotosService.saveCompanyPhotos(companyPhoto);
        log.info("数据库写入结束");

//        log.info("清理缓存结束");
        return true;
    }

    @Override
    public Boolean deletePhotoByUrl(String url) {
        if (Strings.isEmpty(url)) {
            log.info("路径为空删除失败!: {}", url);
            throw new BaseException("路径为空删除失败" + url);
        }

        LambdaQueryWrapper<CompanyPhoto> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CompanyPhoto::getLocation, url);
        companyPhotosService.remove(queryWrapper);
        log.info("数据库记录已删除");

        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucket)
                            .object(url)
                            .build()
            );
        } catch (Exception e) {
            throw new BaseException("minio文件删除失败");
        }

        log.info("图片删除成功!");
        return true;
    }

    //获取文件的md5
    private String getFileMd5(File file) {
        try (FileInputStream fileInputStream = new FileInputStream(file)) {
            return DigestUtils.md5DigestAsHex(fileInputStream);
        } catch (Exception e) {
            log.error("获取文件md5失败");
            return null;
        }
    }

}
